package models

import (
	"fmt"
	"gorm.io/gorm"
	"time"
	cDto "tuowei.com/common/dto"
	"tuowei.com/common/models"
	"tuowei.com/pkg/xlog"
)

type PayMethod int

// 支付方式
const (
	WechatPayMethod  PayMethod = 1 // 微信支付
	AliPayMethod     PayMethod = 2 // 支付宝
	BalancePayMethod PayMethod = 3 // 余额
	CashPayMethod    PayMethod = 4 // 线下
)

type BaseOrder struct {
	models.Model
	models.ModelTime
	OrderNumber string  `gorm:"type:varchar(64);not null;default:'';index;comment:订单编号" json:"order_number"`
	BuyerId     int     `gorm:"type:int(10);not null;default:0;index;comment:买家id" json:"buyer_id"`
	Subject     string  `gorm:"-" json:"subject"`
	SubjectId   int     `gorm:"type:int(10);column:"subject_id",not null;default:0;comment:科目id" json:"subjectId"`
	Province    string  `gorm:"type:varchar(8);not null;default:'';comment:适用大区" json:"province"`
	Price       float64 `gorm:"type:decimal(10,2);comment:价格" json:"price"`
	Commission  float64 `gorm:"type:decimal(10,2);comment:佣金" json:"commission"`
	//InviterId   int     `gorm:"type:int(10);not null;default 0;comment:邀请人id" json:"inviter_id"`
	Postage float64 `gorm:"type:decimal(10,2);comment:邮费" json:"postage"`
	// 关联的购买者的信息 belongs to的关系
	Customer        *SysStudent `gorm:"foreignKey:buyer_id;references:id" json:"customer"`
	SubjectRelation *SysSubject `gorm:"foreignKey:subject_id;references:id" json:"-"`
	PayMethod       int         `gorm:"type:tinyint(1);comment:支付方式" json:"pay_method"`
	TheScore        float64     `gorm:"type:decimal(10,2);comment:本次订单获得积分" json:"the_score"`
	PayAt           string      `json:"pay_at" gorm:"comment:支付时间"`
	// 上级用户
	//Inviter *SysStudent `gorm:"foreignKey:inviter_id;references:id" json:"inviter"`
}

type LinkOrder struct {
	models.Model
	models.ModelTime
	//商品类型OnlineOrder，MaterialOrder,LiveOrder
	OrderType   string `gorm:"type:varchar(64);default:'';comment:关联的订单类型" json:"order_type"`
	OrderId     int    `gorm:"type:int(10);default:0;index;comment:关联的订单id" json:"order_id"`
	Status      int    `gorm:"type:tinyint(2);not null;default:1;comment:订单状态1->未付款，2-已付款，3-招待发货，4-待收货，5-完成" json:"status"`
	BuyerId     int    `gorm:"type:int(10);not null;default:0;index;comment:买家id" json:"buyer_id"`
	OrderNumber string `gorm:"type:varchar(64);not null;default:'';index;comment:订单编号" json:"order_number"`
}

func (on LinkOrder) TableName() string {

	return "sys_link_order"
}

// 在线订单
type OnlineOrder struct {
	BaseOrder
	CourseId      int               `gorm:"type:int(10);not null;default:0;comment:课程id" json:"course_id"`
	TeacherId     int               `gorm:"type:int(10);not null;default 0;comment:教师id" json:"teacher_id"`
	Status        int               `gorm:"type:tinyint(2);not null;default 1;comment:订单状态 1-未付款，2-已经付款" json:"status"`
	CourseType    string            `json:"course_type" gorm:"type:varchar(50);comment:课程类型，online，live"` //课程类型
	OrderType     string            `gorm:"-" json:"order_type"`
	Teacher       *SysLecturer      `gorm:"foreignKey:buyer_id;references:id" json:"teacher"`
	Course        []*SysCourse      `gorm:"many2many:online_order_course;foreignKey:id;joinForeignKey:order_id;References:course_id;joinReferences:course_id"`
	CourseCount   []*SysCourseCount `gorm:"-" json:"course_count"`
	ShareId       int               `gorm:"type:int(10);not null;default 0;comment:分享者学生id" json:"share_id"`
	IsBindOffline int               `json:"is_bind_offline" gorm:"tinyint(1);default:0;comment:是否关联面授课程"`
}

type OnlineOrderCount struct {
	BaseOrder
	CourseId    int               `gorm:"type:int(10);not null;default:0;comment:课程id" json:"course_id"`
	TeacherId   int               `gorm:"type:int(10);not null;default 0;comment:教师id" json:"teacher_id"`
	Status      int               `gorm:"type:tinyint(2);not null;default 1;comment:订单状态 1-未付款，2-已经付款" json:"status"`
	Teacher     *SysLecturer      `gorm:"foreignKey:buyer_id;references:id" json:"teacher"`
	Course      []*SysCourse      `gorm:"many2many:online_order_course;foreignKey:id;joinForeignKey:order_id;References:course_id;joinReferences:course_id"`
	CourseCount []*SysCourseCount `gorm:"-" json:"course_count"`
}
type SysCourseCount struct {
	Course *SysCourse `json:"course"`
	Count  int        `json:"count"`
}

func (on OnlineOrder) TableName() string {

	return "sys_online_order"
}

type Contract struct {
	models.Model
	ProvinceId  int    `json:"province_id" gorm:"province_id"`   //省份id
	Date        string `json:"date" gorm:"date"`                 //年份，四位
	ContractNum int    `json:"contract_num" gorm:"contract_num"` //编号
	models.ModelTime
}

func (c Contract) TableName() string {
	return "contract"
}

func (c Contract) GetMaxContractNumAndInsert(db *gorm.DB, provinceId int, date string) (int, error) {
	var obj Contract
	err := db.Model(c).Where("province_id = ?", provinceId).Where("date = ?", date).
		Order("id desc").First(&obj).Error
	var number int
	var found bool
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			found = false
		} else {
			return number, err
		}
	} else {
		found = true
	}
	// 找到则更新
	if found {
		obj.ContractNum++
		err = db.Save(&obj).Error
		return obj.ContractNum, err
	} else {
		// 找不到则插入一条
		obj.ContractNum = 1
		obj.ProvinceId = provinceId
		obj.Date = date
		err = db.Create(&obj).Error
		return obj.ContractNum, err
	}
}

// 根据学生id查询网课历史订单
func (on OnlineOrder) GetStudentList(db *gorm.DB, list *[]OnlineOrder, buyerId, pageIndex, pageSize int) error {
	err := db.Preload("Course").Preload("SubjectRelation").
		Where("buyer_id = ?", buyerId).
		Scopes(cDto.Paginate(pageSize, pageIndex)).
		Order("id desc").
		Find(list).Error
	for k, v := range *list {
		xlog.Error(v.SubjectRelation)
		if v.SubjectRelation != nil {
			xlog.Error(v.SubjectRelation)
			(*list)[k].Subject = v.SubjectRelation.Name
		}
	}
	return err
}

const (
	OfflineStatusSubmit       = 1
	OfflineStatusFollowIng    = 2
	OfflineStatusFinanceCheck = 3
	OfflineStatusComplete     = 4
)

// 线下订单
type OfflineOrder struct {
	BaseOrder
	CourseId     int `gorm:"type:int(10);not null;default:0;comment:课程id" json:"course_id"`
	DepartmentId int `gorm:"type:int(10);not null;default 0;comment:最基层部门id" json:"department_id"`
	//提交->待跟进-》招生跟进-》财务复审-》完成。
	Status              int                     `gorm:"type:tinyint(2);not null;default 1;comment:订单状态1->提交，2-待跟进，3-财务复审，4-完成 " json:"status"`
	Course              []*SysOfflineCourse     `gorm:"many2many:offline_order_course;foreignKey:id;joinForeignKey:order_id;References:course_id;joinReferences:course_id"`
	Department          *SysTeachingPoint       `gorm:"foreignKey:dept_id;references:id" json:"department"` // 不该名字，直接改成复用到教学点
	FollowUp            string                  `json:"follow_up" comment:"跟进意见"`
	ContractNo          string                  `json:"contract_no" comment:"合同编号"`
	Recheck             string                  `json:"recheck" comment:"复审意见"`
	Communication       string                  `gorm:"type:varchar(512);default:'';comment:沟通记录" json:"communication"`
	CompletePay         int                     `gorm:"type:tinyint(1);default:0;comment:是否完成付款，0-未完成，1-已完成"`
	DeptId              int                     `gorm:"type:int(10);default:0;comment:教学点" json:"dept_id"`
	Name                string                  `gorm:"type:varchar(50);default:'';comment:买家姓名" json:"name"`
	Phone               string                  `gorm:"type:varchar(20);default:'';comment:买家电话" json:"phone"`
	TeachingPointId     int                     `gorm:"type:int(10);default:0;comment:教学点" json:"teaching_point_id"`
	EnrollmentTeacherId int                     `gorm:"type:int(10);default:0;comment:招生老师" json:"enrollment_teacher_id"`
	ReceiptNumber       string                  `gorm:"type:varchar(255);column:receipt_number" json:"receipt_number"`     //收据编号
	AgreementNumber     string                  `gorm:"type:varchar(255);column:agreement_number" json:"agreement_number"` //协议编号
	ActualIncome        float64                 `gorm:"type:decimal(10,2);column:actual_income" json:"actual_income"`      //实际收款
	CollegeId           int                     `gorm:"type:int(10);default:0;comment:"院校id" json:"college_id"`
	Grade               string                  `gorm:"type:varchar(200);default:'';comment:年级" json:"grade"`
	KeBie               string                  `gorm:"type:varchar(200);default:'';comment:科别" json:"ke_bie"`
	Records             []*OfflineOrderProgress `gorm:"foreignKey:order_id;references:id" json:"records"`
	Year                int                     `gorm:"type:int;default:0;comment:订单年份" json:"year"`
	Month               int                     `gorm:"type:int;default:0;comment:订单月份" json:"month"`
	OrderType           string                  `gorm:"-" json:"order_type"`
	OfflineCount        []*SysOfflineCount      `gorm:"-" json:"course_count"` //保持和在线订单一致的key
	RecheckUserId       int                     `json:"recheck_user_id" gorm:"comment:RecheckUserId"`
	RecheckUser         *SysUser                `gorm:"foreignKey:recheck_user_id;references:user_id"`
	ContractUrl         string                  `json:"contract_url" comment:"合同编号url"`
	ContractNumber      string                  `json:"contract_number" gorm:"comment:电子合同编号"`
	FileId              string                  `json:"file_id" gorm:"comment:e签正式生成的合同问下下载的文件id"`
	Signed              int                     `json:"signed" gorm:"comment:是否签过字,默认0么有,1有"`
	SignFlowId          string                  `json:"sign_flow_id" gorm:"comment:e签签署流程id"`
}

type SysOfflineCount struct {
	OfflineCourse *SysOfflineCourse `json:"course"` //保持和在线订单一致的key
	Count         int               `json:"count"`
}

func (o OfflineOrder) TableName() string {
	return "sys_offline_order"
}

// 根据学生id查询历史订单
func (o OfflineOrder) GetStudentList(db *gorm.DB, list *[]OfflineOrder, buyerId, pageIndex, pageSize int) error {
	err := db.Preload("Course").Preload("SubjectRelation").
		Where("buyer_id = ?", buyerId).
		Scopes(cDto.Paginate(pageSize, pageIndex)).
		Order("id desc").
		Find(list).Error
	for k, v := range *list {
		xlog.Error(v.SubjectRelation)
		if v.SubjectRelation != nil {
			xlog.Error(v.SubjectRelation)
			(*list)[k].Subject = v.SubjectRelation.Name
		}
	}
	return err
}

// 获取线下订单半年历史记录
func (o OfflineOrder) GetNealHalfYearHistoryList(db *gorm.DB, buyerId, orderId int) ([]OfflineOrder, error) {
	lists := make([]OfflineOrder, 0)
	err := db.Preload("Customer.Recommenders").Preload("Customer.TeachRecommenders").
		Preload("Department").Preload("SubjectRelation").
		Where("buyer_id = ?", buyerId).Where("id != ?", orderId).
		Where("created_at > ?", time.Now().Add(-180*24*time.Hour)).Find(&lists).Error
	for k := range lists {
		if lists[k].SubjectRelation != nil {
			lists[k].Subject = lists[k].SubjectRelation.Name
		}
	}
	return lists, err
}

// 资料订单

type MaterialOrder struct {
	BaseOrder
	Status             int            `gorm:"type:tinyint(2);not null;default 1;comment:订单状态1->未付款，2-已付款，3-招待发货，4-待收货，5-完成 " json:"status"`
	Comments           string         `gorm:"type:varchar(255);not null;default:'';comment:备注" json:"comments"`
	ExpressNumber      string         `gorm:"type:varchar(255);not null;default:'';comment:快递单号" json:"express_number"`
	ExpressCompany     string         `gorm:"type:varchar(255);not null;default:'';comment:快递公司" json:"express_company"`
	ExpressCompanyName string         `gorm:"-" json:"express_company_name"`
	MaterialId         int            `gorm:"type:int(10);not null;default:0;comment:资料id" json:"material_id"`
	OrderType          string         `gorm:"-" json:"order_type"`
	Material           []*SysMaterial `gorm:"many2many:material_order_material;foreignKey:id;joinForeignKey:order_id;References:id;joinReferences:material_id"`
	//PayAt          string              `json:"pay_at" gorm:"comment:付款日期" json:"pay_at"`
	Address       string              `gorm:"type:varchar(255);not null;default:'';comment:收获地址" json:"address"`
	MaterialCount []*SysMaterialCount `gorm:"-" json:"course_count"` //保持和在线订单一致的key
	DeliverId     int                 `gorm:"type:int(10);not null;default 0;comment:发货人id" json:"deliver_id"`
	DeliverUser   *SysUser            `gorm:"foreignKey:deliver_id;references:user_id"`
	SendAt        time.Time           `json:"send_at" gorm:"comment:发货时间"`
}
type SysMaterialCount struct {
	Material *SysMaterial `json:"course"` //保持和在线订单一致的key
	Count    int          `json:"count"`
}

func (mo MaterialOrder) TableName() string {
	return "sys_material_order"
}

// 资料订单半年历史
func (mo MaterialOrder) GetNealHalfYearHistoryList(db *gorm.DB, buyerId, orderId int) ([]MaterialOrder, error) {
	lists := make([]MaterialOrder, 0)
	err := db.Preload("Customer.Recommenders").Preload("Customer.TeachRecommenders").
		Preload("Material").Preload("SubjectRelation").
		Where("buyer_id = ?", buyerId).Where("id != ?", orderId).
		Where("created_at > ?", time.Now().Add(-180*24*time.Hour)).Find(&lists).Error
	for k := range lists {
		if lists[k].SubjectRelation != nil {
			lists[k].Subject = lists[k].SubjectRelation.Name
		}
	}
	return lists, err
}

type OnlineOrderCourse struct {
	OrderId  int `json:"order_id" gorm:"index;not null;type:int;comment:订单id"`
	CourseId int `json:"course_id" gorm:"index;not null;type:int;comment:课程id"`
}

func (o OnlineOrderCourse) TableName() string {
	return "online_order_course"
}

func (on OnlineOrder) GetNealHalfYearHistoryList(db *gorm.DB, buyerId, orderId int) ([]OnlineOrder, error) {
	lists := make([]OnlineOrder, 0)
	err := db.Preload("Customer.Recommenders").Preload("Customer.TeachRecommenders").
		Preload("Teacher").Preload("SubjectRelation").
		Where("buyer_id = ?", buyerId).Where("id != ?", orderId).
		Where("created_at > ?", time.Now().Add(-180*24*time.Hour)).Find(&lists).Error
	for k := range lists {
		if lists[k].SubjectRelation != nil {
			lists[k].Subject = lists[k].SubjectRelation.Name
		}
	}
	return lists, err
}

type OfflineOrderCourse struct {
	OrderId  int `json:"order_id" gorm:"index;not null;type:int;comment:订单id"`
	CourseId int `json:"course_id" gorm:"index;not null;type:int;comment:课程id"`
}

func (o OfflineOrderCourse) TableName() string {
	return "offline_order_course"
}

type MaterialOrderMaterial struct {
	OrderId    int `json:"order_id" gorm:"index;not null;type:int;comment:订单id"`
	MaterialId int `json:"material_id" gorm:"index;not null;type:int;comment:资料id"`
}

func (o MaterialOrderMaterial) TableName() string {
	return "material_order_material"
}

// 线下订单记录表
type OfflineOrderProgress struct {
	models.Model
	Creator     string    `json:"creator" gorm:"type:varchar(32);not null;default:0;comment:操作者"`
	Status      int       `json:"status" gorm:"type:tinyint(2);not null;comment:操作时候的订单状态"`
	OrderId     int       `json:"order_id" gorm:"index;type:int;not null;default 0;comment:订单id"`
	OperateTime time.Time `json:"operate_time" gorm:"comment:操作时间"`
	FollowUp    string    `json:"follow_up" gorm:"column:follow_up;type:varchar(512);comment:跟进记录"`
	Remarks     string    `json:"remarks" gorm:"column:remarks;type:varchar(512);comment:备注"`
}

func (o OfflineOrderProgress) TableName() string {
	return "offline_order_progress"
}

// GetStudentCount 获取某个招生的订单数量
func (o OfflineOrder) GetStudentCount(db *gorm.DB, teacherId, status int) int {
	var count int64
	rawSql := fmt.Sprintf("SELECT count(*) as count FROM sys_offline_order AS o INNER JOIN sys_student AS s "+
		"ON o.buyer_id = s.id "+
		"WHERE s.enrollment_teacher_id = %d ", teacherId)
	if status > 0 {
		rawSql = fmt.Sprintf("SELECT count(*) as count FROM sys_offline_order AS o INNER JOIN sys_student AS s "+
			"ON o.buyer_id = s.id "+
			"WHERE s.enrollment_teacher_id = %d AND "+
			"o.status = %d", teacherId, status)
	}
	db.Table(o.TableName()).Raw(rawSql).Count(&count)
	return int(count)
}
